﻿using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using NHibernate;
using NHibernate.Linq;
using NHibernate.Transform;

namespace NHibernateInsight.Tests.Insights.Linq.Extensions
{
    public static class NHibernateLinqExtensions
    {
        public static ICriteria AsCriteriaQuery<T>(this INHibernateQueryable<T> nhQueryable)
        {
            var queryProvider = nhQueryable.Provider as NHibernateQueryProvider;
            if (queryProvider == null) return null;

            var translated = queryProvider.TranslateExpression(nhQueryable.Expression);
            if (translated == null) return null;

            return translated as ICriteria;
        }
        public static INHibernateQueryable<T> ExpandQuery<T>(this INHibernateQueryable<T> nhQueryable, Action<ICriteria> expand_query_with)
        {
            nhQueryable.QueryOptions.RegisterCustomAction(expand_query_with);

            return nhQueryable;            
        }
        public static INHibernateQueryable<T> DistinctRoot<T>(this INHibernateQueryable<T> nhQueryable)
        {
            nhQueryable.QueryOptions.RegisterCustomAction(c => c.SetResultTransformer(new DistinctRootEntityResultTransformer()));
            
            return nhQueryable;
        }

        public static INHibernateQueryable<T> Cached<T>(this INHibernateQueryable<T> nhQueryable)
        {
            nhQueryable.QueryOptions.RegisterCustomAction(c => c.SetCacheable(true));

            return nhQueryable;
        }
        public static INHibernateQueryable<T> Cached<T>(this INHibernateQueryable<T> nhQueryable, string cacheRegion)
        {
            nhQueryable.QueryOptions.RegisterCustomAction(c =>
                                                              {
                                                                  c.SetCacheable(true);
                                                                  c.SetCacheRegion(cacheRegion);
                                                              });


            return nhQueryable;
        }
        public static INHibernateQueryable<T> CacheMode<T>(this INHibernateQueryable<T> nhQueryable, CacheMode cacheMode)
        {
            nhQueryable.QueryOptions.RegisterCustomAction(c => c.SetCacheMode(cacheMode));

            return nhQueryable;
        }

        public static INHibernateQueryable<T> Flush<T>(this INHibernateQueryable<T> nhQueryable, FlushMode flushMode)
        {
            nhQueryable.QueryOptions.RegisterCustomAction(c => c.SetFlushMode(flushMode));

            return nhQueryable;
        }
        public static INHibernateQueryable<T> Lock<T>(this INHibernateQueryable<T> nhQueryable, LockMode lockMode)
        {
            nhQueryable.QueryOptions.RegisterCustomAction(c => c.SetLockMode(lockMode));

            return nhQueryable;
        }
        public static INHibernateQueryable<T> FetchSize<T>(this INHibernateQueryable<T> nhQueryable, int fetchSize)
        {
            nhQueryable.QueryOptions.RegisterCustomAction(c => c.SetFetchSize(fetchSize));

            return nhQueryable;
        }
        public static INHibernateQueryable<T> Timeout<T>(this INHibernateQueryable<T> nhQueryable, int timeout)
        {
            nhQueryable.QueryOptions.RegisterCustomAction(c => c.SetTimeout(timeout));

            return nhQueryable;
        }
    }
}
